
#pragma once

#include "ql.h"

struct ReaderContext;
typedef struct ReaderContext ReaderContext;

typedef void (* ReaderErrorCallback)( struct ReaderContext * reader_context, ErrResult msg );

/*
 * default size of the buffer for identifiers and strings
 * not including terminating zero symbol
 */
#define QL_DEFAULT_MAX_STR_SIZE     511

/*
 * initializes reader context
 * @param AllocContext *    ac              specifies allocation context
 * @param FILE *            stream
 * @param const char *      stream_name
 * @return ReaderContext                    newly created reader context. Can't be null, so null-checks can be omitted
 */
ReaderContext * create_reader(
    AllocContext *      ac,
    FILE *              stream,
    const char *        stream_name
    );

/*
 * initializes reader context
 * @param ReaderContext *   ac              specifies certain reader context
 * @param size_t            max_str_size    size of the buffer for identifiers and strings; if 0
 *                                          is provided QL_DEFAULT_MAX_STR_SIZE will be used instead
 */
void
set_reader_max_str_size( ReaderContext * reader, size_t max_str_size );

/*
 * associotes given user-side tag with reader
 */
void set_reader_tag( ReaderContext * reader, void * tag );

/*
 * retrieves associated reader tag.
 * if no tag was associated before, 0 will be returned
 */
void * get_reader_tag( ReaderContext * reader );

/*
 * if read_obj returns null pointer, last error can be retrieved by using this
 * function
 */
ErrResult reader_get_last_error( ReaderContext * reader );

/*
 * reads certain object from reader
 */
Obj * read_obj( ReaderContext * reader );

/*
 * sets default namespace, old value will be returned
 */
Id * set_default_namespace( ReaderContext * reader, Id * default_namespace );

Id * get_default_namespace( ReaderContext * r );

int reader_line( ReaderContext * reader );

int reader_pos( ReaderContext * reader );

const char * reader_stream_name( ReaderContext * reader );

/*
 * frees internal data what is allocated within read_obj
 */
void free_reader( ReaderContext * reader );
